use crate::sbi::console_putchar; // src/sbi.rs 中 的 console_putchar()
use core::fmt::{self, Write}; // 导入 core::fmt::Write 特性，是为了使用 Write 的其他方法

struct Stdout; // 类单元结构体

impl Write for Stdout {
    // 现实了你，就可以用另一个write_fmt方法了，它可以让我们使用格式化的字符串
    fn write_str(&mut self, s: &str) -> fmt::Result {
        // 写字符串就是把字符一个个传给真正输出字符的地方
        for c in s.chars() {
            console_putchar(c as usize);
        }
        Ok(())
    }
}

pub fn print(args: fmt::Arguments) {
    Stdout.write_fmt(args).unwrap();
}

#[macro_export]
macro_rules! print {
    ($fmt: literal $(, $($arg: tt)+)?) => {
        $crate::console::print(format_args!($fmt $(, $($arg)+)?));
    }
}

#[macro_export]
macro_rules! println {
    ($fmt: literal $(, $($arg: tt)+)?) => {
        $crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
    }
}

#[macro_export]
macro_rules! log {
    ($level: ident, $fmt: literal $(, $($arg: tt)+)?) => {
        match stringify!($level) {
            "error" => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR] ", $fmt, "\x1b[0m\n") $(, $($arg)+)?)),
            "warn" => $crate::console::print(format_args!(concat!("\x1b[93m[WARN] ", $fmt, "\x1b[0m\n") $(, $($arg)+)?)),
            "info" => $crate::console::print(format_args!(concat!("\x1b[34m[INFO] ", $fmt, "\x1b[0m\n") $(, $($arg)+)?)),
            "debug" => $crate::console::print(format_args!(concat!("\x1b[32m[DEBUG] ", $fmt, "\x1b[0m\n") $(, $($arg)+)?)),
            "trace" => $crate::console::print(format_args!(concat!("\x1b[90m[TRACE] ", $fmt, "\x1b[0m\n") $(, $($arg)+)?)),
            _ => $crate::console::print(format_args!("0")),
        }
    }
}
